﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Practices.ESB.Resolver;
using Microsoft.Practices.ESB.Resolver.BRE;
using Microsoft.Practices.ESB.Exception.Management;
using Microsoft.XLANGs.BaseTypes;
using System.Reflection;
using BizTalk.ESB.Extensions.Helpers;

namespace BizTalk.ESB.Extensions.Resolvers
{
    public class AssociatedFileResolution
    {
        public string DocumentType { get; set; }
        public string PolicyName { get; set; }
        public string BreTracePath { get; set; }
        public string FolderPath { get; set; }
        public string FileName { get; set; }
        public string FileExtension { get; set; }
        public string ContentType { get; set; }
        public bool Merge { get; set; }
    }

    public class AssociatedFileResolutionManager
    {
        public static BRE CreateResolverDescriptor(string config, string resolver)
        {
            BRE breWrapper;

            if (config == null)
            {
                throw new ArgumentNullException("config");
            }
            if (resolver == null)
            {
                throw new ArgumentNullException("resolver");
            }

            Dictionary<String, String> facts = null;
            try
            {
                BRE breTemp = new BRE();
                breTemp.useMsg = false;
                facts = ResolverMgr.GetFacts(config, resolver);
                breTemp.policy = ResolverMgr.GetConfigValue(facts, true, "policy");
                breTemp.version = ResolverMgr.GetConfigValue(facts, false, "version");
                Boolean useMessage, recognizeMessage;
                breTemp.useMsgSpecified = Boolean.TryParse(
                    ResolverMgr.GetConfigValue(facts, false, "useMsg")
                    , out useMessage);
                breTemp.recognizeMessageFormatSpecified = Boolean.TryParse(
                    ResolverMgr.GetConfigValue(facts, false, "recognizeMessageFormat")
                    , out recognizeMessage);
                breTemp.useMsg = useMessage;
                breTemp.recognizeMessageFormat = recognizeMessage;

                breWrapper = breTemp;
            }
            catch (Exception e)
            {
                EventLogger.Write(MethodBase.GetCurrentMethod(), e);
                throw;
            }
            finally
            {
                if (facts != null)
                {
                    facts.Clear();
                    facts = null;
                }
            }

            return breWrapper;
        }

        public static void SetResolverDictionary(AssociatedFileResolution resolution, Dictionary<String, String> dictionary)
        {
            try
            {
                dictionary.Add("Resolver.DocumentType", resolution.DocumentType);
                dictionary.Add("Resolver.PolicyName", resolution.PolicyName);
                dictionary.Add("Resolver.BreTracePath", resolution.BreTracePath);
                dictionary.Add("Resolver.FolderPath", resolution.FolderPath);
                dictionary.Add("Resolver.FileName", resolution.FileName);
                dictionary.Add("Resolver.FileExtension", resolution.FileExtension);
                dictionary.Add("Resolver.ContentType", resolution.ContentType);
                dictionary.Add("Resolver.Merge", resolution.Merge.ToString());
            }
            catch { }
        }

        public static void SetContext(AssociatedFileResolution resolution, XLANGMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }
            if (resolution == null)
            {
                throw new ArgumentNullException("resolution");
            }
            try
            {
                resolution.DocumentType = ((string)AssociatedFileResolutionManager.GetMsgProperty(message
                    , typeof(BTS.SchemaStrongName))) ?? String.Empty;
                if (String.IsNullOrEmpty(resolution.DocumentType) == false)
                {
                    int index = resolution.DocumentType.IndexOf(",", StringComparison.CurrentCultureIgnoreCase);
                    if ((index > 0) && (index < resolution.DocumentType.Length))
                    {
                        resolution.DocumentType = resolution.DocumentType.Substring(0, index);
                    }
                }
            }
            catch (Exception e)
            {
                EventLogger.Write(MethodBase.GetCurrentMethod(), e);
                throw;
            }
        }

        private static Object GetMsgProperty(XLANGMessage message, Type property)
        {
            Object prop;
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }
            if (property == null)
            {
                throw new ArgumentNullException("property");
            }
            Object PropertyValue = null;
            try
            {
                PropertyValue = message.GetPropertyValue(property);
                prop = PropertyValue;
            }
            catch (Exception e)
            {
                EventLogger.Write(MethodBase.GetCurrentMethod(), e);
                throw;
            }
            finally
            {
                if (PropertyValue != null)
                {
                    PropertyValue = null;
                }
            }
            return prop;
        }
    }
}
